/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package colordrips;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 * Formulário que representará o campo de jogo.
 * @author SimaoItalo
 */

public class PlayingField extends javax.swing.JFrame implements MouseListener, Listener {

    private ArrayList<ArrayList<Block>> matrixBlocks = new ArrayList<ArrayList<Block>>();
    private Player player;
    private HomeScreen homeScreen;
    
    private Runnable thread = new Runnable() {

        @Override
        public void run() {
            try {
                Thread.sleep(200);
                rearrangeMatrix();
            } catch (Exception ex) {
                System.err.println("Erro na thread: " + ex);
            }
            
        }
    };
    
    /**
     * Construtor do Campo de Jogo
     * @param playerName 
     */
    public PlayingField(String playerName, HomeScreen homeScreen) {
        this.player = new Player(playerName);
        this.homeScreen = homeScreen;
        initComponents();
        Block.listeners.add(this);
        lbGameOver.setVisible(false);
        organizeLabels();
        lbQtBlocks.setText("    60");
    }
    
    /**
     * Método que organiza os labels no campo de jogo
     * com o uso dos métodos "fillMatrix" e "addLabelsInField"
     */
    private void organizeLabels(){
        
        if(!matrixBlocks.isEmpty()){
            matrixBlocks.clear();
        }
        
        fillMatrix();
        
        addLabelsInField();
        
        addMouseListenersOnLabels();
        
    }
    
    /**
     * Método que preenche a matriz de labels
     */
    private void fillMatrix(){
       for (int i = 0; i < 8; i++){
            for (int j = 0; j < 12; j++){
                if(((i == 0) || (i == 7)) || ((j == 0) || (j == 11))){
                    matrixBlocks.add(new ArrayList<Block>());
                    matrixBlocks.get(i).add(j, new Block(i, j, true));
                } else {
                    matrixBlocks.add(new ArrayList<Block>());
                    matrixBlocks.get(i).add(j, new Block(i, j, false));
                }
            }
        } 
    }
    
    /**
     * Método que adiciona os lables no campo
     */
    private void addLabelsInField(){
        matrixBlocks.get(1).get(1).setBounds(0, 0, 50, 50);
        panelField.add(matrixBlocks.get(1).get(1));
        for(int i = 2; i < 7; i++){
            int y = matrixBlocks.get(i-1).get(1).getY() + 50;
            matrixBlocks.get(i).get(1).setBounds(0, y, 50, 50);
            panelField.add(matrixBlocks.get(i).get(1));
        }
        
        int x = 0;
        int y = 0;
        
        for (int i = 1; i < 7; i++){
            if (i != 1){
                y = (matrixBlocks.get(i-1).get(i).getY() + 50);
            } 
            for (int j = 2; j < 11; j++){
                x = (matrixBlocks.get(i).get(j-1).getX() + 50);
                matrixBlocks.get(i).get(j).setBounds(x, y, 50, 50);
                panelField.add(matrixBlocks.get(i).get(j));
                System.out.println("Cor: " + matrixBlocks.get(i).get(j).getColor());
            }
        }
    }
    
    /**
     * Método que adiciona os eventos de mouse nos labels do campo de jogo.
     */
    private void addMouseListenersOnLabels(){
        for (int i = 1; i < 7; i++){
            for (int j = 1; j < 11; j++){
                matrixBlocks.get(i).get(j).addMouseListener(this);
            }
        } 
    }
    
    /**
     * Método que faz um rearranjo na matriz, de forma a fazer o reajuste de lihas e colunas.
     */
    private void rearrangeMatrix(){
        GameLogic.adjustColors(matrixBlocks);
        GameLogic.adjustLines(matrixBlocks);
        cleanField();
        addLabelsInField();
        redesign();
        GameLogic.adjustColumns(matrixBlocks);
        cleanField();
        addLabelsInField();
        redesign();
    }
    
    /**
     * Método que limpa o painel onde estão localizados os labels do campo de jogo.
     */
    private void cleanField(){
        panelField.removeAll();
    }
    
    /**
     * Método que redesenha os labels do campo, setando novamente suas imagens.
     */
    private void redesign(){
        for (int i = 1; i < 7; i++){
            for (int j = 1; j < 11; j++){
                //System.out.println(matrixBlocks.get(i).get(j).getColor() + " ");
                switch(matrixBlocks.get(i).get(j).getColor()){
                    case "blue":
                        if(!matrixBlocks.get(i).get(j).isEmpty()){
                            matrixBlocks.get(i).get(j).setImage("/assets/circle_blue48.png");   
                        }
                        break;
                    case "red":
                        if(!matrixBlocks.get(i).get(j).isEmpty()){
                            matrixBlocks.get(i).get(j).setImage("/assets/circle_red48.png");   
                        }
                        break;
                    case "orange":
                        if(!matrixBlocks.get(i).get(j).isEmpty()){
                            matrixBlocks.get(i).get(j).setImage("/assets/circle_orange48.png");
                        }
                        break;
                    case "green":
                        if(!matrixBlocks.get(i).get(j).isEmpty()){
                            matrixBlocks.get(i).get(j).setImage("/assets/circle_green48.png");
                        }
                        break;
                }
            }
        } 
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        panelField = new javax.swing.JPanel();
        lbGameOver = new javax.swing.JLabel();
        lbQtBlocks = new javax.swing.JLabel();
        lbBackGround = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Color Drips");
        setMinimumSize(new java.awt.Dimension(628, 496));
        setResizable(false);
        getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        panelField.setBackground(new java.awt.Color(0, 0, 0));
        panelField.setMinimumSize(new java.awt.Dimension(300, 500));
        panelField.setOpaque(false);
        panelField.setPreferredSize(new java.awt.Dimension(300, 500));

        lbGameOver.setText("jLabel1");

        javax.swing.GroupLayout panelFieldLayout = new javax.swing.GroupLayout(panelField);
        panelField.setLayout(panelFieldLayout);
        panelFieldLayout.setHorizontalGroup(
            panelFieldLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFieldLayout.createSequentialGroup()
                .addContainerGap(69, Short.MAX_VALUE)
                .addComponent(lbGameOver, javax.swing.GroupLayout.PREFERRED_SIZE, 374, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(57, 57, 57))
        );
        panelFieldLayout.setVerticalGroup(
            panelFieldLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelFieldLayout.createSequentialGroup()
                .addGap(24, 24, 24)
                .addComponent(lbGameOver, javax.swing.GroupLayout.PREFERRED_SIZE, 205, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(271, Short.MAX_VALUE))
        );

        getContentPane().add(panelField, new org.netbeans.lib.awtextra.AbsoluteConstraints(62, 125, 500, 350));

        lbQtBlocks.setFont(new java.awt.Font("Corbel", 1, 18)); // NOI18N
        lbQtBlocks.setToolTipText("Quantidade de peças");
        getContentPane().add(lbQtBlocks, new org.netbeans.lib.awtextra.AbsoluteConstraints(130, 464, 60, 20));

        lbBackGround.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/bg3g.png"))); // NOI18N
        getContentPane().add(lbBackGround, new org.netbeans.lib.awtextra.AbsoluteConstraints(0, 0, -1, 500));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(PlayingField.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(PlayingField.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(PlayingField.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(PlayingField.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new PlayingField("", new HomeScreen()).setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel lbBackGround;
    private javax.swing.JLabel lbGameOver;
    private javax.swing.JLabel lbQtBlocks;
    private javax.swing.JPanel panelField;
    // End of variables declaration//GEN-END:variables

    /**
     * Implementação do mouseClicked
     * Ao clicar num label, ele verifica se aquela é uma jogada válida, se for, ele realiza a jogada
     * de acordo com as regras do jogo.
     */
    @Override
    public void mouseClicked(MouseEvent e) {
        
        Block selectedBlock = (Block)e.getSource();
        
        if(GameLogic.isAPossibleMove(matrixBlocks, selectedBlock)){
            System.out.println("is a possible move");
            GameLogic.removeBlocks(matrixBlocks, selectedBlock);
            lbQtBlocks.setText("    " + GameLogic.checkNumberOfBlocks(matrixBlocks));
        } else {
            System.out.println("isn't a possible move");
        }
        //Thread t = new Thread(thread);
        //t.start(); // faz o rearranjo da matriz (reajuste de linhas e colunas, redesign)
        rearrangeMatrix();
        if(!GameLogic.hasPossibleMoves(matrixBlocks)){
            try {
                System.out.println("Acabou o jogo carai.");
    //            lbGameOver.setIcon(new ImageIcon(getClass().getResource("/assets/gameover_alert.png")));
    //            lbGameOver.setVisible(true);
                int qtOfBlocks = GameLogic.checkNumberOfBlocks(matrixBlocks);
                JOptionPane pane = new JOptionPane();
                pane.showMessageDialog(this, "Game Over \nRestaram: " + qtOfBlocks + " bolas !");
                this.dispose();
                this.homeScreen.setVisible(true);
            } catch (Throwable ex) {
                System.err.println("Erro: " + ex);
            }
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
        
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        
    }

    /**
     * Implementação do mouseEntered
     * Ao entrar na área do label, ele verifica a cor do mesmo, e então muda a imagem
     * para uma editada.
     */
    @Override
    public void mouseEntered(MouseEvent e) {
        Block selectedBlock = (Block)e.getSource();
        switch(selectedBlock.getColor()){
            case "blue":
                if(!selectedBlock.isEmpty()){
                    selectedBlock.setImage("/assets/circle_blue48_80a.png");
                }
                break;
            case "red":
                if(!selectedBlock.isEmpty()){
                    selectedBlock.setImage("/assets/circle_red48_80a.png");
                }
                break;
            case "orange":
                if(!selectedBlock.isEmpty()){
                    selectedBlock.setImage("/assets/circle_orange48_80a.png");
                }
                break;
            case "green":
                if(!selectedBlock.isEmpty()){
                    selectedBlock.setImage("/assets/circle_green48_80a.png");
                }
                break;
        }
    }

    /**
     * Implementação do mouseClicked
     * Método disparado quando o mouse sai da área do label, mudando sua imagem para a original.
     */
    @Override
    public void mouseExited(MouseEvent e) {
        Block selectedBlock = (Block)e.getSource();
        switch(selectedBlock.getColor()){
            case "blue":
                if(!selectedBlock.isEmpty()){
                    selectedBlock.setImage("/assets/circle_blue48.png");
                }
                break;
            case "red":
                if(!selectedBlock.isEmpty()){
                    selectedBlock.setImage("/assets/circle_red48.png");
                }
                break;
            case "orange":
                if(!selectedBlock.isEmpty()){
                    selectedBlock.setImage("/assets/circle_orange48.png");
                }
                break;
            case "green":
                if(!selectedBlock.isEmpty()){
                    selectedBlock.setImage("/assets/circle_green48.png");
                }
                break;
        }
    }

    /**
     * Implementação do mouseClicked
     * Método chamado quando algum bloco é "retirado" da matriz de labels.
     */
    @Override
    public void executeAction() {
        redesign();
    }
}
